package ar.com.logic.components;

import ar.com.logic.components.actualizadores.ActualizadorManager;
import ar.com.logic.components.interfaces.IHistoricoRespuestas;
import ar.com.logic.components.interfaces.IMatrizPosiciones;
import ar.com.logic.components.strategy.IEstrategia;
import ar.com.logic.components.strategy.SelectorEstrategia;
import ar.com.logic.evaluador.Evaluador;
import ar.com.logic.evaluador.Respuesta;

public class NPC {
	private IMatrizPosiciones matrizPosiciones;
	private IHistoricoRespuestas historicoResultados;
	private SelectorEstrategia poolEstrategias;
	private Integer maxPosiciones;
	private Integer maxDigitos;
	private ActualizadorManager actualizadorManager;

	public NPC(Integer maxPosiciones, Boolean incluyeCero) {
		this.actualizadorManager = new ActualizadorManager();
		this.matrizPosiciones = new MatrizPosiciones(incluyeCero, maxPosiciones);

		this.historicoResultados = new HistoricoRespuestas(maxPosiciones,
				incluyeCero);
		this.poolEstrategias = new SelectorEstrategia(matrizPosiciones,
				historicoResultados);
		this.maxPosiciones = maxPosiciones;
		if (incluyeCero) {
			this.maxDigitos = 10;
		} else {
			this.maxDigitos = 9;
		}

	}

	public Resultado deducirNumero(Evaluador eval) {

		Resultado r = new Resultado();
		IEstrategia e;
		Respuesta resp;
		while (!r.resuelto()) {
			r.addIntentos();
			e = poolEstrategias.elegirEstrategia(historicoResultados
					.obtenerUltimaRespuesta());
			Numero siguienteNumero = e.getSiguienteNumero();
			if (siguienteNumero.equals(new Numero("0000"))) {
				resp = eval.evaluar(eval.getNumero());
			} else {
				resp = eval.evaluar(siguienteNumero);
			}
			this.historicoResultados.add(resp);
			this.actualizarMatriz(resp);
			this.actualizarSemiFijos(resp);
			System.out.println(resp);
			System.out.println(this.matrizPosiciones);
			System.out.println(this.historicoResultados);

			if (resp.resuelto()) {
				r.setNumeroResultado(resp.getNumero());
			}
		}

		return r;

	}

	private void actualizarSemiFijos(Respuesta resp) {
		if (historicoResultados.getNumerosNoUtilizados().size() == maxDigitos
				- (historicoResultados.getUltimoTurno() * maxPosiciones)) {
			if (historicoResultados
					.obtenerTotalEncontradosEnNUltimasRespuestas(historicoResultados
							.getUltimoTurno()) >= maxPosiciones) {

				for (Integer noUtilizado : historicoResultados
						.getNumerosNoUtilizados()) {
					matrizPosiciones.descartarValor(noUtilizado);
				}
				historicoResultados.borrarNoUtilizados();
			}

		}

	}

	private void actualizarMatriz(Respuesta resp) {

		actualizadorManager.actualizar(matrizPosiciones, historicoResultados);

	}

	public IMatrizPosiciones getMatrizPosiciones() {
		return matrizPosiciones;
	}

	public IHistoricoRespuestas getHistoricoResultados() {
		return historicoResultados;
	}

}
